home *** CD-ROM | disk | FTP | other *** search
- /*
- * mgrterm - a terminal emulator for MiNT/mgr
- * term loop based on a very simple term emu by
- * david@doe.utoronto.ca (David Megginson)
- *
- * ++jrb bammi@cadence.com
- */
-
- /*
- * Menus:
- *
- * Main Menu Baud Dial FlowControl
- * --------- ---- ---- -----------
- * Suspend 19200 ph#1 None
- * Baud => 9600 .. Rts/Cts
- * Dial => 2400 Xon/Xoff
- * ToggleDuplex 1200 .. Both
- * FlowControl => 300 ph#n
- * StuffTermcap
- * Shell
- * Status
- * =============
- * Quit
- *
- */
-
- /* Whitepages
- * the whitepages file may either be specified
- * - on the command line
- * - via the WHITEPAGES environment variable
- * - otherwise the default below is used if it exists
- * - if no white pages exits, the menu entry will contain a dummy.
- * The dial pull right menu is paged, 15 entries/page.
- *
- * The whitepages files can contain
- * - comments lines - begining with '#'
- * - blank lines
- * - entries
- * a whitepages entry is for the form (max length of an entry == 132)
- * name : [baud] : [dial string]
- *
- * the name is the key. only enough characters to make the search
- * unambigious need be specified. imbedded blanks are significant.
- * leading and trailing one are ignored. case is significant.
- *
- * if no baud is specified, then the present baud rate is not changed,
- * otherwise the baud rate is set when the entry is chosen. leading and
- * trailing blanks are ignored. if the baud specified is invalid, the dial
- * is aborted.
- *
- * if a dial string is specified, it is sent to the modem with interpretation.
- * leading blanks are ignored. tailing ones are significant. the dial string
- * is interpreted as follows:
- * \n, \r, \\ send newline, carriage return and backslash respectively.
- * \nnn send octal char nnn
- * \s<number> sleep for <number> seconds
- * \t<number> set char wait timeout to <number> seconds (default 10 seconds)
- * \w<char> wait until char, all chars occuring in the mean while
- * are skipped. Abort dial on timeout. the char maybe
- * specified in its octal form \nnn (\r etc not recognized).
- *
- * examples:
- * unix direct login : 19200 : \w:bammi\r\w:mypasswd\r
- * # switch to 19200 baud, wait for ':' send string "bammi\r" wait for ':'
- * # send string "mypasswd\r". use default char wait timeout period.
- * unix dialup : 2400 : atdt5551212\w:bammi\r\w:mypasswd\r
- * compuserve : 2400 : atdt5551515\w2\w4\w0\w0\r\w:CIS\r\w:71515,111\r\w:xxx\r
- * timbaktu :: atdt1timbaktu\r
- * # use current baud rate
- * 2400 : 2400 :
- * # just change baud rate
- *
- */
- #include <stddef.h>
- #include <stdlib.h>
- #include <osbind.h>
- #include <mintbind.h>
- #include <string.h>
- #include <setjmp.h>
- #include <signal.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <term.h>
- #include "proto.h"
-
- #ifndef Bconmap
- #define Bconmap(dev) (short)trap_14_ww((short)(0x2c), (short)(dev))
- #endif
-
- #define Bconws(s) Boutput(2, (s))
- #define CTRL(x) ((x) & 0x1f)
- #define ESCAPE 0x001D /* CTRL-] */
- #define QUIT 0x0080 /* <UNDO> */
- #define MAXWAIT 20000L /* Maximum number of failed attempts */
- /* to read a character before we */
- /* start snoozing */
- #define MIDIDEV 3 /* bios midi dev id */
-
- int mgr = 1; /* mgr not pure MiNT */
- int half = 0; /* doing half duplex */
- int rsdev = 1; /* serial line */
- char *phones = NULL; /* whitepages file */
- char *default_phones = "d:/etc/white";
- int baud; /* current baud rate */
- int flow = 0; /* current flow */
- int olddev = 0x2c;
-
- typedef struct {
- char *name;
- char *baud;
- char *number;
- } WHITEPAGE;
-
- WHITEPAGE *whitepages = 0; /* white pages entries */
-
- int main(int argc, const char **argv)
- {
- unsigned long counter = 0;
- unsigned short c;
- extern char *optarg;
- extern int optind, opterr;
-
- while((c = getopt(argc, argv, "P:")) != -1)
- {
- switch(c)
- {
- case 'P':
- rsdev = atoi(optarg);
- if(rsdev != MIDIDEV)
- olddev = Bconmap(rsdev);
- break;
- case '?':
- Bconws((char *)(argv[0])); Bconws(" [-P serial device] [whitepages file]\r\n");
- exit(1);
- }
- }
- if(optind < argc)
- phones = (char *)(argv[optind]);
-
- init();
- do{
- /* We haven't found any activity yet */
- counter++;
-
- /* Check for a character from the modem */
- if( Bconstat(rsdev) ) {
- counter = 0;
- c = ((int)Bconin(rsdev)) & 0x7f;
- Bconout(2,c);
- }
-
- /* Check for a character from the cons */
- if( Bconstat(2) ) {
- counter = 0;
- c = ((int)Bconin(2)) & 0x00FF;
- if( c == QUIT )
- do_quit();
- else if( (c &= 0x7f) == ESCAPE )
- do_escape();
- else
- {
- Bconout(rsdev,c);
- if(half)
- Bconout(2, c);
- }
- }
-
- /* Don't soak up CPU time if there is */
- /* nothing going on! */
- if( counter >= MAXWAIT )
- Syield();
- } while( 1 );
- return 0;
- }
-
- struct {
- int id;
- char *str;
- } men[] = {
- {1, "\005\
- Suspend \005\
- BaudRate ==>\005\
- DialNumber ==>\005\
- ToggleDuplex \005\
- FlowControl ==>\005\
- StuffTermcap \005\
- ShellCommand \005\
- PrintStatus \005\
- -----------------\005\
- Quit \005\
- \035z\005\
- \035b\005\
- \035d\005\
- \035h\005\
- \035f\005\
- \035t\005\
- \035!\005\
- \035s\005\
- \005\
- \035q\005" },
- { 2, "\005\
- 19200 \005\
- 9600 \005\
- 4800 \005\
- 3600 \005\
- 2400 \005\
- 2000 \005\
- 1800 \005\
- 1200 \005\
- 600 \005\
- 300 \005\
- 200 \005\
- 150 \005\
- 134 \005\
- 110 \005\
- 75 \005\
- 50 \005\
- 19200\r\005\
- 9600\r\005\
- 4800\r\005\
- 3600\r\005\
- 2400\r\005\
- 2000\r\005\
- 1800\r\005\
- 1200\r\005\
- 600\r\005\
- 300\r\005\
- 200\r\005\
- 150\r\005\
- 134\r\005\
- 110\r\005\
- 75\r\005\
- 50\r\005" },
- {3, "\005\
- None \005\
- Rts/Cts \005\
- Xon/Xoff \005\
- Both \005\
- n\r\005\
- r\r\005\
- x\r\005\
- b\r\005" },
- {0, (char *)0 }}, default_dial =
- { 4, "\005\
- none \005\
- ATH\r\005" };
-
- int ndialmenus; /* number of dial sub menus menus */
- int ndial; /* number of whitepages entries */
- int lastm; /* last menu before dial menus(or first dial menu) */
-
- _IOREC *iorec_p, save_iorec;
- char myrsbuf[16384];
- char linebuf[132];
-
- void init(void)
- {
- char *getenv(const char *);
- char *s = getenv("TERM");
-
- if(s)
- mgr = !strcmp(s, "mgr");
- else
- mgr = 1; /* no TERM -- assume mgr */
-
- iorec_p = (_IOREC *)Iorec((rsdev == MIDIDEV)? 2 : 0);
- save_iorec = *iorec_p;
- iorec_p->ibuf = myrsbuf;
- iorec_p->ibufsiz = sizeof(myrsbuf);
- iorec_p->ibuflow = sizeof(myrsbuf) >> 3;
- iorec_p->ibufhi = (sizeof(myrsbuf) >> 2) * 3;
- iorec_p->ibufhd = iorec_p->ibuftl = 0;
- if(rsdev != MIDIDEV)
- {
- baud = Rsconf(-2, -1, -1, -1, -1, -1);
- Rsconf(-1, 0, -1, -1, -1, -1);
- }
- else
- {
- baud = 16;
- flow = 0;
- }
- if(!phones)
- phones = getenv("WHITEPAGES");
- if(!phones)
- phones = default_phones;
- if(access(phones, R_OK))
- phones = NULL;
- if(phones) read_whitepages(phones);
-
- if( mgr )
- {
- m_setup(M_FLUSH|M_DEBUG);
- m_push(P_FLAGS|P_MENU);
- m_setmode(M_BACKGROUND);
- download_menus();
- }
- }
-
- void do_quit(void)
- {
- int i;
-
- *iorec_p = save_iorec;
- Bconws("\r\n");
- if( mgr )
- {
- m_nomenu();
- for(i = ndialmenus+lastm-1; i > lastm; i--)
- {
- m_unpagemenu(i-1);
- }
- m_unlinkmenu(1, 2);
- m_unlinkmenu(1, 4);
- m_unlinkmenu(1, 1);
-
- for(i = lastm; i < ndialmenus+lastm; i++)
- m_clearmenu(i);
- for(i = 0; men[i].id; i++)
- m_clearmenu(men[i].id);
- m_pop();
- }
- if((rsdev != MIDIDEV) && (olddev != 0x2c))
- (void)Bconmap(olddev);
- exit(0);
- }
-
- void download_menus(void)
- {
- int i, j, k, l, len;
-
- for(i = 0; men[i].id; i++)
- {
- m_loadmenu(men[i].id, men[i].str);
- lastm = men[i].id;
- }
- m_linkmenu(1, 1, 2, 0);
- m_linkmenu(1, 4, 3, 0);
- i = ++lastm;
- if(whitepages)
- {
- for(j = 0; (j < ndial) && (whitepages[j].name); j += 15)
- {
- #if 0
- printf("Downloading %d\n", i);
- #endif
- fprintf(m_termout,"%c%d,", m_escchar, i);
- for(len = 0, k = j; (k < (j+15)) && whitepages[k].name; k++)
- len += (((int)strlen(whitepages[k].name)) + 1) * 2 + 1;
- fprintf(m_termout, "%d%c", len+1, E_MENU);
- strcpy(linebuf, "\005");
- for(l = 0; l < 2; l++)
- {
- for(k = j; (k < (j+15)) && whitepages[k].name; k++)
- {
- strcat(linebuf, whitepages[k].name);
- if(l == 0)
- strcat(linebuf, "\005");
- else
- strcat(linebuf, "\r\005");
- fprintf(m_termout, "%s", linebuf);
- strcpy(linebuf, "");
- }
- }
- fflush(m_termout);
- #if 0
- printf("Done Downloading %d(%d)\n", i, len+1);
- #endif
- if(i != lastm)
- {
- m_pagemenu(i-1, i);
- #if 0
- printf("Page %d to %d\n", i, i-1);
- #endif
- }
- i++;
- if(!(whitepages[k].name)) break;
- }
- ndialmenus = i - lastm;
- }
- else
- {
- m_loadmenu(lastm, default_dial.str);
- ndialmenus = 1;
- }
- m_linkmenu(1, 2, lastm, 0);
- m_selectmenu(1);
- #if 0
- printf("%d dial menus\n", ndialmenus);
- #endif
- }
-
- char *prompt = "\r\nenter one of z b d h f t ! s q or ? for help: ";
- char *help = "\r\n\n\
- \tz\t\tto suspend\r\n\
- \tb speed\t\tto set baud rate\r\n\
- \td num\t\tto dial number\r\n\
- \th\t\tto toggle duplex\r\n\
- \tf nrxb\t\tto set flow control\r\n\
- \tt\t\tto stuff termcap\r\n\
- \t! cmd\t\tto execute cmd\r\n\
- \ts\t\tto print status\r\n\
- \tq\t\tto quit\r\n\
- or <return> to cancel\r\n\n";
-
- #define EECHO(c) if(!mgr) Bconout(2, (c))
-
- void do_escape(void)
- {
- int c, done = 0;
-
- while(!done)
- {
- if(!mgr)
- Bconws(prompt);
- c = Bconin(2) & 0x7f;
- EECHO(c);
- done = 1;
- switch(c)
- {
- case '?':
- Bconws(help);
- done = 0;
- break;
- case '!':
- do_shell();
- break;
- case 'b': case 'B':
- do_baud();
- break;
- case 'q': case 'Q':
- do_quit();
- break;
- case 'z': case 'Z': case '\032': /* ctl-z */
- do_stop();
- break;
- case '\r':
- Bconout(2, '\n');
- break;
- case '\n':
- Bconout(2, '\r');
- break;
- case 'd': case 'D':
- do_dial();
- break;
- case 'h': case 'H':
- do_duplex();
- break;
- case 'f': case 'F':
- do_flow();
- break;
- case 't': case 'T':
- do_termcap();
- break;
- case 's': case 'S':
- do_status();
- break;
- default:
- done = 0;
- }
- }
- }
-
-
- char *getline(int echo)
- {
- char *l = linebuf;
- int c;
-
- while(! rindex("\n\r", (c = Bconin(2) &0x7f)) )
- {
- switch(c)
- {
- case '\b': case '\177':
- if(echo) Bconws("\b \b");
- break;
- case CTRL('U'):
- if(echo)
- while(l-- != linebuf) Bconws("\b \b");
- l = linebuf;
- break;
- default:
- *l++ = c;
- if(echo) Bconout(2, c);
- }
- }
- if(echo)
- Bconws("\r\n");
- *l = '\0';
- l = linebuf;
- while((*l == ' ') || (*l == '\t')) l++;
- return l;
- }
-
- void do_shell(void)
- {
- char *s;
-
- if(mgr)
- {
- m_nomenu();
- Bconws("\r\ncmd: ");
- }
- s = getline(1);
- if(!(*s))
- goto ret;
-
- system(s);
- Bconws("\r\nhit <return> to continue");
- (void)getline(1);
- ret:
- if( mgr )
- {
- m_selectmenu(1);
- }
- }
-
- struct {
- char *string;
- int value;
- } bauds[] = {
- { "19200", 0 },
- { "9600", 1 },
- { "4800", 2 },
- { "3600", 3 },
- { "2400", 4 },
- { "2000", 5 },
- { "1800", 6 },
- { "1200", 7 },
- { "600", 8 },
- { "300", 9 },
- { "200", 10 },
- { "150", 11 },
- { "134", 12 },
- { "110", 13 },
- { "75", 14 },
- { "50", 15 },
- { "MidiBaud", 16},
- { (char *)0, -1}
- };
-
- void do_baud(void)
- {
- char *s;
-
- while(1)
- {
- s = getline(!mgr);
- if(!(*s))
- return;
-
- if(set_baud(s))
- Bconws("Unknown baud rate, enter again or <return> to cancel: ");
- else
- return;
- }
- }
-
- int set_baud(char *s)
- {
- int i;
- for(i = 0; bauds[i].string; i++)
- {
- if(strcmp(s, bauds[i].string) == 0)
- {
- if(rsdev != MIDIDEV)
- {
- Rsconf(bauds[i].value, -1, -1, -1, -1, -1);
- baud = bauds[i].value;
- }
- return 0;
- }
- }
- return 1;
- }
-
- #include <signal.h>
- void do_stop(void)
- {
- unsigned long omask;
-
- if(mgr)
- {
- m_nomenu();
- }
- Bconws("\r\n");
- omask = Psigsetmask(0L);
- (void) Pkill(0, SIGTSTP);
- (void) Psigsetmask(omask);
- if( mgr )
- {
- m_selectmenu(1);
- }
- }
-
- void do_duplex(void)
- {
- half = !half;
- }
-
- struct {
- char c;
- char *string;
- } flows[] = {
- { 'n', "none" },
- { 'r', "Rts/Cts" },
- { 'x', "Xon/Xoff" },
- { 'b', "both" },
- { '\377', (char *)0 }
- };
-
- void do_flow(void)
- {
- int i, c;
- if(!mgr)
- {
- Bconws("\r\nn(none) r(rts/cts) x(xon/xoff) or b(both): ");
- }
- while(1)
- {
- c = *(getline(!mgr));
- if(c == '\0')
- return;
- for (i = 0; flows[i].c != '\377'; i++)
- {
- if(flows[i].c == c)
- {
- if(rsdev != MIDIDEV)
- {
- Rsconf(-1, i, -1, -1, -1, -1);
- flow = i;
- }
- return;
- }
- }
- Bconws("Unknown flow type, enter again or <return> to cancel: ");
- }
- }
-
- char *atermcap = "\
- atari|st52|Atari ST without al dl:\\\r\
- :am:bl=^G:bs:cd=\\EJ:ce=\\EK:cl=\\EE:cm=\\EY%+ %+ :co#80:\\\r\
- :do=^J:eo:ho=\\EH:is=\\Eq\\EE\\Ee\\Ev:it#8:le=^H:li#25:ll=\\EY9!:\\\r\
- :me=\\Eq:mr=\\Ep:nd=\\EC:rc=\\Ek:sc=\\Ej:se=\\Eq:so=\\Ep:ta=^I:\\\r\
- :ti=\\Eq\\Ev\\Ee:up=\\EA:ve=\\Ee:vi=\\Ef:";
-
- void do_termcap(void)
- {
- char *termcap = (mgr)? get_termcap() : atermcap;
- if(termcap)
- {
- int l = strlen(termcap) - 1;
-
- if((termcap[l] == '\n') || (termcap[l] == '\r'))
- {
- if(termcap[l-1] == '\r')
- termcap[l-1] = '\0';
- else
- termcap[l] = '\0';
- }
- Boutput(rsdev, "setenv TERMCAP '");
- Boutput(rsdev, termcap);
- Boutput(rsdev,"'\r");
- }
- }
-
- void do_status(void)
- {
- Bconws("\r\nMgrterm $Revision: 1.4 $\r\n");
- Bconws("\tBaud rate: "); Bconws(bauds[baud].string);
- Bconws("\r\n\tFlow type: "); Bconws(flows[flow].string);
- Bconws("\r\n\tSerial dev: "); Bconout(2, (rsdev+'0'));
- Bconws("\r\n\tWhitepages: "); Bconws((phones)? phones:"none"); Bconws("\r\n");
- }
-
- void Boutput(int dev, char *s)
- {
- for( ; *s ; s++)
- Bconout(dev, *s);
- }
-
- /* dialing stuff */
-
- void do_dial(void)
- {
- char *s = getline(!mgr);
- int i;
- size_t len;
-
- if((!(*s)) || (!whitepages))
- return;
- len = strlen(s);
- for(i = 0; whitepages[i].name; i++)
- {
- if(!strncmp(whitepages[i].name, s, len))
- {
- if((*(whitepages[i].baud)) &&
- strcmp(bauds[baud].string, whitepages[i].baud))
- {
- if(set_baud(whitepages[i].baud))
- {
- Bconws("\r\nInvalid baud rate ");Bconws(whitepages[i].baud);
- Bconws(" for "); Bconws(whitepages[i].name);
- Bconws(" dial aborted\r\n");
- return;
- }
- Bconout(rsdev, '\r');
- }
- send_dial(whitepages[i].number);
- return;
- }
- }
- Bconws("\r\n"); Bconws(s); Bconws(": unlisted in whitepages\r\n");
- }
-
- #if __STDC__
- char * strdup(const char *s);
- #else
- extern char *strdup();
- #endif
-
- void read_whitepages(char *file)
- {
- int pass, n = 0, i = 0;
- FILE *fp = fopen(file, "r");
- char *s, *p, *q, *r, *next;
-
- if(!fp)
- {
- Bconws("\r\nCant find "); Bconws(file);
- Bconws(" Continuing without it\r\n");
- return;
- }
- for(pass = 0; pass < 2; pass++)
- {
- do {
- do {
- if((s = fgets(linebuf, sizeof(linebuf), fp)) == NULL)
- break;
- while((*s == ' ') || (*s == '\t')) s++;
- } while((*s == '#') || (*s == '\n') || (*s == '\r'));
- if(s == NULL)
- {
- if(pass == 0)
- {
- if((whitepages = (WHITEPAGE *)malloc((n+1) * sizeof(WHITEPAGE))) == NULL)
- {
- goto nomem;
- }
- fseek(fp, 0L, SEEK_SET);
- bzero(whitepages, (n+1) * sizeof(WHITEPAGE));
- }
- break;
- }
- if(pass == 0)
- {
- n++;
- continue;
- }
- s[(strlen(s) - 1)] = '\0';
- p = s;
- q = index(p, ':');
- if((!q) || (q == p))
- {
- Invalid:
- Bconws("Invalid entry: "); Bconws(s);
- Bconws("\r\n Continuing without it\r\n");
- if(whitepages[i].name) free(whitepages[i].name);
- whitepages[i].name = NULL;
- continue;
- }
- next = q+1;
- for(--q; ((*q == ' ') || (*q == '\t')); --q) ;
- *++q = '\0';
- if(!(r = strdup(p)))
- goto nomem;
- whitepages[i].name = r;
- p = next;
- while((*p == ' ') || (*p == '\t')) p++;
- q = index(p, ':');
- if(!q) goto Invalid;
- next = q+1;
- if(q == p)
- *q = '\0';
- else
- {
- for(--q; ((*q == ' ') || (*q == '\t')); --q) ;
- *++q = '\0';
- }
- if(!(r = strdup(p)))
- goto nomem;
- whitepages[i].baud = r;
- p = next;
- while((*p == ' ') || (*p == '\t')) p++;
- if(!(r = strdup(p)))
- goto nomem;
- whitepages[i].number = r;
- i++;
- } while(1);
- }
- if(i == 0)
- {
- if(whitepages)
- free(whitepages);
- whitepages == NULL;
- ndial = 0;
- goto closeup;
- }
- if(i != n)
- whitepages = realloc(whitepages, sizeof(WHITEPAGE)*(i+1));
- if(!whitepages) goto nomem;
- ndial = i; /* # of whitepages entries */
- closeup:
- fclose(fp);
- #if 0
- printf("Found %d entries\n", ndial);
- for(i = 0; i < ndial; i++)
- printf("%s %s %s\n", whitepages[i].name, whitepages[i].baud,
- whitepages[i].number);
- #endif
- return;
-
- nomem:
- fclose(fp);
- if(whitepages)
- {
- for(i = 0; whitepages[i].name; i++)
- {
- free(whitepages[i].name);
- if(whitepages[i].baud) free(whitepages[i].baud);
- if(whitepages[i].number) free(whitepages[i].number);
- }
- free(whitepages);
- }
- whitepages = NULL;
- ndial = 0;
- Bconws("\r\nNot enough memory for whitepages, continuing without them\r\n");
- return;
- }
-
- #define isnumber(c) (((c) >= '0') && ((c) <= '9'))
- int timeout = 10; /* char wait timeout */
-
- void send_dial(char *s)
- {
- char c;
-
- for(; (c = *s) ; s++)
- {
- if(c != '\\')
- {
- Bconout(rsdev, c);
- if(half) Bconout(2, c);
- continue;
- }
- switch((c = *++s))
- {
- case 'r':
- Bconout(rsdev, '\r'); if(half) Bconout(2, '\r'); break;
- case 'n':
- Bconout(rsdev, '\n'); if(half) Bconout(2, '\n'); break;
- case '\\':
- Bconout(rsdev, '\\'); if(half) Bconout(2, '\\'); break;
- case 's':
- sleep(getnum(&s, 10)); break;
- case 't':
- timeout = getnum(&s, 10); if(timeout == 0) timeout = 10; break;
- case 'w':
- if((c = *++s) == '\\') c = getnum(&s, 8);
- if(await_char(c))
- {
- Bconws("\r\nCharacter wait time out\r\n");
- return;
- }
- break;
- default:
- if(isnumber(c))
- {
- unsigned char n = 0;
- int i = 0;
- do {
- n = (n << 3) | (c - '0');
- c = *++s;
- i++;
- } while(isnumber(c) && (i < 3));
- --s;
- Bconout(rsdev, n); if(half) Bconout(2, n);
- }
- else
- {
- Bconws("\r\nIllegal dial string escape, skipped\r\n");
- if(!(*s)) return;
- }
- }
- }
- }
-
- int getnum(char **stringp, int base)
- {
- char *s = *stringp;
- int n = 0;
-
- for(++s; isnumber(*s); s++)
- {
- n = n * base + (*s - '0');
- }
- *stringp = --s;
- return (n < 0)? 0 : n;
- }
-
- jmp_buf alrm_buf;
-
- void alrm(void)
- {
- Psigreturn();
- longjmp(alrm_buf, -1);
- }
-
- int await_char(int ch)
- {
- int c;
- void (*save)(void) = signal(SIGALRM, alrm);
-
- if(setjmp(alrm_buf))
- {
- (void)signal(SIGALRM, save);
- return 1;
- }
-
- alarm(timeout);
- while((c = Bconin(rsdev) & 0x7f) != ch)
- Bconout(2, c);
- alarm(0);
- Bconout(2, c);
- (void)signal(SIGALRM, save);
- return 0;
- }
-